/**
 * Copyright 2019-2022 Huawei Technologies Co., Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "aipp_para_impl.h"

#include <map>
#include <set>
#include <string>

#include "framework/infra/log/log.h"
#include "framework/c/hiai_tensor_aipp_para.h"
#include "c/hcl/hiai_tensor_aipp_para.h"
#include "infra/base/securestl.h"
#include "infra/base/assertion.h"

#ifdef __OHOS__
#include "model_manager/general_model_manager/ndk/hiai_ndk/hiai_ndk_create_itf.h"
#include "model_manager/general_model_manager/ndk/ndk_util/ndk_util.h"
#endif

namespace {

using namespace hiai;
using namespace std;
const float kFloat16Max = 65504;
const float kFloat16Lowest = -kFloat16Max;
const uint8_t g_maxBatchNum = 127;


static Status CheckBatchIndex(uint32_t batchIndex, uint32_t batchNum)
{
    if (batchIndex >= batchNum) {
        FMK_LOGE("batchIndex [%zu] is not supported.", batchIndex);
        return FAILURE;
    }
    return SUCCESS;
}

static _Float16 SaveUint16ToFp16(uint16_t num)
{
    _Float16* uintAddr = nullptr;
    uintAddr = reinterpret_cast<_Float16*>(&num);
    return *uintAddr;
}

static uint16_t SaveFp16ToUint16(_Float16 num)
{
    uint16_t* uintAddr = nullptr;
    uintAddr = reinterpret_cast<uint16_t*>(&num);
    return *uintAddr;
}

static Status UpdateCropPara(HIAI_MR_TensorAippPara* paraBuff, uint32_t batchIndex, const CropPara& cropPara)
{
    HIAI_EXPECT_EXEC(
        AIPPParaBufferImpl::SetCropPos(paraBuff, batchIndex, cropPara.cropStartPosW, cropPara.cropStartPosH));
    HIAI_EXPECT_EXEC(AIPPParaBufferImpl::SetCropSize(paraBuff, batchIndex, cropPara.cropSizeW, cropPara.cropSizeH));
    return SUCCESS;
}

static Status UpdateResizePara(HIAI_MR_TensorAippPara* paraBuff, uint32_t batchIndex,
    const ResizePara& resizePara)
{
    return AIPPParaBufferImpl::SetResizePara(paraBuff, batchIndex,
        resizePara.resizeOutputSizeW, resizePara.resizeOutputSizeH);
}

static Status UpdatePaddingPara(HIAI_MR_TensorAippPara* paraBuff, uint32_t batchIndex, const PadPara& paddingPara)
{
    HIAI_EXPECT_EXEC(AIPPParaBufferImpl::SetPadTopSize(paraBuff, batchIndex, paddingPara.paddingSizeTop));
    HIAI_EXPECT_EXEC(AIPPParaBufferImpl::SetPadBottomSize(paraBuff, batchIndex, paddingPara.paddingSizeBottom));
    HIAI_EXPECT_EXEC(AIPPParaBufferImpl::SetPadLeftSize(paraBuff, batchIndex, paddingPara.paddingSizeLeft));
    HIAI_EXPECT_EXEC(AIPPParaBufferImpl::SetPadRightSize(paraBuff, batchIndex, paddingPara.paddingSizeRight));

    float value = std::max(std::min(paddingPara.paddingValueChn0, kFloat16Max), kFloat16Lowest);
    uint32_t paddingValueChn0 = static_cast<uint32_t>(SaveFp16ToUint16(value));
    value = std::max(std::min(paddingPara.paddingValueChn1, kFloat16Max), kFloat16Lowest);
    uint32_t paddingValueChn1 = static_cast<uint32_t>(SaveFp16ToUint16(value));
    value = std::max(std::min(paddingPara.paddingValueChn2, kFloat16Max), kFloat16Lowest);
    uint32_t paddingValueChn2 = static_cast<uint32_t>(SaveFp16ToUint16(value));
    value = std::max(std::min(paddingPara.paddingValueChn3, kFloat16Max), kFloat16Lowest);
    uint32_t paddingValueChn3 = static_cast<uint32_t>(SaveFp16ToUint16(value));

    uint32_t chnValue[] = {paddingValueChn0, paddingValueChn1, paddingValueChn2, paddingValueChn3};

    HIAI_EXPECT_EXEC(AIPPParaBufferImpl::SetPadChannelValue(paraBuff, batchIndex, chnValue, 4));
    return SUCCESS;
}

Status UpdateDtcPara(HIAI_MR_TensorAippPara* paraBuff, uint32_t batchIndex, const DtcPara& dtcPara)
{
    int32_t pixelMeanPara[4] = {
        static_cast<int32_t>(dtcPara.pixelMeanChn0), static_cast<int32_t>(dtcPara.pixelMeanChn1),
        static_cast<int32_t>(dtcPara.pixelMeanChn2), static_cast<int32_t>(dtcPara.pixelMeanChn3)};

    float dtcPixelMinChn0 = std::max(std::min(dtcPara.pixelMinChn0, kFloat16Max), kFloat16Lowest);
    float dtcPixelMinChn1 = std::max(std::min(dtcPara.pixelMinChn1, kFloat16Max), kFloat16Lowest);
    float dtcPixelMinChn2 = std::max(std::min(dtcPara.pixelMinChn2, kFloat16Max), kFloat16Lowest);
    float dtcPixelMinChn3 = std::max(std::min(dtcPara.pixelMinChn3, kFloat16Max), kFloat16Lowest);
    float pixelMinPara[4] = {dtcPixelMinChn0, dtcPixelMinChn1, dtcPixelMinChn2, dtcPixelMinChn3};

    float dtcPixelVarReciChn0 = std::max(std::min(dtcPara.pixelVarReciChn0, kFloat16Max), kFloat16Lowest);
    float dtcPixelVarReciChn1 = std::max(std::min(dtcPara.pixelVarReciChn1, kFloat16Max), kFloat16Lowest);
    float dtcPixelVarReciChn2 = std::max(std::min(dtcPara.pixelVarReciChn2, kFloat16Max), kFloat16Lowest);
    float dtcPixelVarReciChn3 = std::max(std::min(dtcPara.pixelVarReciChn3, kFloat16Max), kFloat16Lowest);

    float pixelVarReciPara[4] = {dtcPixelVarReciChn0, dtcPixelVarReciChn1, dtcPixelVarReciChn2, dtcPixelVarReciChn3};

    HIAI_EXPECT_EXEC(AIPPParaBufferImpl::SetDtcPixelMeanPara(paraBuff, batchIndex, pixelMeanPara, 4));
    HIAI_EXPECT_EXEC(AIPPParaBufferImpl::SetDtcPixelMinPara(paraBuff, batchIndex, pixelMinPara, 4));
    HIAI_EXPECT_EXEC(AIPPParaBufferImpl::SetDtcPixelVarReciPara(paraBuff, batchIndex, pixelVarReciPara, 4));
    return SUCCESS;
}

Status UpdateRotatePara(HIAI_MR_TensorAippPara* paraBuff, uint32_t batchIndex,
    const RotatePara& rotatePara)
{
    return AIPPParaBufferImpl::SetRotatePara(paraBuff, batchIndex, rotatePara.rotationAngle);
}
} // namespace

namespace hiai {

HIAI_MR_TensorAippPara* AIPPParaBufferImpl::Init(uint32_t batchCount)
{
    return HIAI_MR_TensorAippPara_Create(batchCount);
}

Status AIPPParaBufferImpl::Release(HIAI_MR_TensorAippPara* paraBuff)
{
    HIAI_MR_TensorAippPara_Destroy(reinterpret_cast<HIAI_MR_TensorAippPara**>(&paraBuff));
    return SUCCESS;
}

void* AIPPParaBufferImpl::GetRawBuffer(HIAI_MR_TensorAippPara* paraBuff)
{
    return HIAI_MR_TensorAippPara_GetRawBuffer(paraBuff);
}

uint32_t AIPPParaBufferImpl::GetRawBufferSize(HIAI_MR_TensorAippPara* paraBuff)
{
    return HIAI_MR_TensorAippPara_GetRawBufferSize(paraBuff);
}

int AIPPParaBufferImpl::GetInputIndex(HIAI_MR_TensorAippPara* paraBuff)
{
    return HIAI_MR_TensorAippPara_GetInputIndex(paraBuff);
}

void AIPPParaBufferImpl::SetInputIndex(HIAI_MR_TensorAippPara* paraBuff, uint32_t inputIndex)
{
    HIAI_MR_TensorAippPara_SetInputIndex(paraBuff, inputIndex);
}

uint32_t AIPPParaBufferImpl::GetBatchCount(HIAI_MR_TensorAippPara* paraBuff)
{
    return HIAI_MR_TensorAippPara_GetBatchCount(paraBuff);
}

int AIPPParaBufferImpl::GetInputAippIndex(HIAI_MR_TensorAippPara* paraBuff)
{
    return HIAI_MR_TensorAippPara_GetInputAippIndex(paraBuff);
}

Status AIPPParaBufferImpl::SetCscPara(HIAI_MR_TensorAippPara* paraBuff, ImageFormat inputFormat,
    ImageFormat targetFormat, ImageColorSpace colorSpace)
{
    return HIAI_MR_TensorAippPara_SetCscPara(paraBuff, static_cast<HIAI_ImageFormat>(inputFormat),
        static_cast<HIAI_ImageFormat>(targetFormat), static_cast<HIAI_ImageColorSpace>(colorSpace));
}

Status AIPPParaBufferImpl::SetCscMatrixPara(HIAI_MR_TensorAippPara* paraBuff, CscMatrixPara cscMatrixPara)
{
    int32_t matrixPara[15] = {0};
    matrixPara[0] = cscMatrixPara.matrixR0C0;
    matrixPara[1] = cscMatrixPara.matrixR0C1;
    matrixPara[2] = cscMatrixPara.matrixR0C2;
    matrixPara[3] = cscMatrixPara.matrixR1C0;
    matrixPara[4] = cscMatrixPara.matrixR1C1;
    matrixPara[5] = cscMatrixPara.matrixR1C2;
    matrixPara[6] = cscMatrixPara.matrixR2C0;
    matrixPara[7] = cscMatrixPara.matrixR2C1;
    matrixPara[8] = cscMatrixPara.matrixR2C2;
    matrixPara[9] = cscMatrixPara.inputBias0;
    matrixPara[10] = cscMatrixPara.inputBias1;
    matrixPara[11] = cscMatrixPara.inputBias2;
    matrixPara[12] = cscMatrixPara.outputBias0;
    matrixPara[13] = cscMatrixPara.outputBias1;
    matrixPara[14] = cscMatrixPara.outputBias2;

    return HIAI_MR_TensorAippPara_SetCscMatrixPara(paraBuff, matrixPara, 15);
}

Status AIPPParaBufferImpl::GetCscPara(HIAI_MR_TensorAippPara* paraBuff, ImageFormat* inputFormat,
    ImageFormat* targetFormat, ImageColorSpace* colorSpace)
{
    return HIAI_MR_TensorAippPara_GetCscPara(paraBuff, reinterpret_cast<HIAI_ImageFormat*>(inputFormat),
        reinterpret_cast<HIAI_ImageFormat*>(targetFormat), reinterpret_cast<HIAI_ImageColorSpace*>(colorSpace));
}

Status AIPPParaBufferImpl::GetCscMatrixPara(HIAI_MR_TensorAippPara* paraBuff, CscMatrixPara* cscMatrixPara)
{
    int32_t matrixPara[15] = {0};
    Status ret = static_cast<Status>(HIAI_MR_TensorAippPara_GetCscMatrixPara(paraBuff, matrixPara, 15));
    if (ret == SUCCESS) {
        cscMatrixPara->matrixR0C0 = matrixPara[0];
        cscMatrixPara->matrixR0C1 = matrixPara[1];
        cscMatrixPara->matrixR0C2 = matrixPara[2];
        cscMatrixPara->matrixR1C0 = matrixPara[3];
        cscMatrixPara->matrixR1C1 = matrixPara[4];
        cscMatrixPara->matrixR1C2 = matrixPara[5];
        cscMatrixPara->matrixR2C0 = matrixPara[6];
        cscMatrixPara->matrixR2C1 = matrixPara[7];
        cscMatrixPara->matrixR2C2 = matrixPara[8];
        cscMatrixPara->inputBias0 = matrixPara[9];
        cscMatrixPara->inputBias1 = matrixPara[10];
        cscMatrixPara->inputBias2 = matrixPara[11];
        cscMatrixPara->outputBias0 = matrixPara[12];
        cscMatrixPara->outputBias1 = matrixPara[13];
        cscMatrixPara->outputBias2 = matrixPara[14];
    }
    return ret;
}

Status AIPPParaBufferImpl::SetChannelSwapPara(HIAI_MR_TensorAippPara* paraBuff, bool rbuvSwapSwitch, bool axSwapSwitch)
{
    return HIAI_MR_TensorAippPara_SetChannelSwapPara(paraBuff, rbuvSwapSwitch, axSwapSwitch);
}

Status AIPPParaBufferImpl::GetChannelSwapPara(HIAI_MR_TensorAippPara* paraBuff,
    bool* rbuvSwapSwitch, bool* axSwapSwitch)
{
    return HIAI_MR_TensorAippPara_GetChannelSwapPara(paraBuff, rbuvSwapSwitch, axSwapSwitch);
}

Status AIPPParaBufferImpl::SetSingleBatchMultiCrop(HIAI_MR_TensorAippPara* paraBuff, bool singleBatchMutiCrop)
{
    return HIAI_MR_TensorAippPara_SetSingleBatchMultiCrop(paraBuff, singleBatchMutiCrop);
}

bool AIPPParaBufferImpl::GetSingleBatchMultiCrop(HIAI_MR_TensorAippPara* paraBuff)
{
    return HIAI_MR_TensorAippPara_GetSingleBatchMultiCrop(paraBuff);
}

void AIPPParaBufferImpl::SetInputAippIndex(HIAI_MR_TensorAippPara* paraBuff, uint32_t inputAippIndex)
{
    return HIAI_MR_TensorAippPara_SetInputAippIndex(paraBuff, inputAippIndex);
}

Status AIPPParaBufferImpl::SetInputFormat(HIAI_MR_TensorAippPara* tensorAippPara, ImageFormat inputFormat)
{
    return HIAI_MR_TensorAippPara_SetInputFormat(tensorAippPara,  static_cast<HIAI_ImageFormat>(inputFormat));
}

ImageFormat AIPPParaBufferImpl::GetInputFormat(HIAI_MR_TensorAippPara* tensorAippPara)
{
    return static_cast<ImageFormat>(HIAI_MR_TensorAippPara_GetInputFormat(tensorAippPara));
}

Status AIPPParaBufferImpl::GetInputShape(HIAI_MR_TensorAippPara* tensorAippPara,
    uint32_t* srcImageW, uint32_t* srcImageH)
{
    return HIAI_MR_TensorAippPara_GetInputShape(tensorAippPara, srcImageW, srcImageH);
}

Status AIPPParaBufferImpl::SetInputShape(HIAI_MR_TensorAippPara* tensorAippPara,
    uint32_t srcImageW, uint32_t srcImageH)
{
    return HIAI_MR_TensorAippPara_SetInputShape(tensorAippPara, srcImageW, srcImageH);
}

Status AIPPParaBufferImpl::SetCropPos(HIAI_MR_TensorAippPara* tensorAippPara,
    uint32_t batchIndex, uint32_t cropStartPosW, uint32_t cropStartPosH)
{
    return HIAI_MR_TensorAippPara_SetCropPos(tensorAippPara, batchIndex, cropStartPosW, cropStartPosH);
}

Status AIPPParaBufferImpl::SetCropSize(HIAI_MR_TensorAippPara* tensorAippPara,
    uint32_t batchIndex, uint32_t cropSizeW, uint32_t cropSizeH)
{
    return HIAI_MR_TensorAippPara_SetCropSize(tensorAippPara, batchIndex, cropSizeW, cropSizeH);
}

Status AIPPParaBufferImpl::GetCropPos(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t* cropStartPosW, uint32_t* cropStartPosH)
{
    return HIAI_MR_TensorAippPara_GetCropPos(tensorAippPara, batchIndex, cropStartPosW, cropStartPosH);
}

Status AIPPParaBufferImpl::GetCropSize(HIAI_MR_TensorAippPara* tensorAippPara,
    uint32_t batchIndex, uint32_t* cropSizeW, uint32_t* cropSizeH)
{
    return HIAI_MR_TensorAippPara_GetCropSize(tensorAippPara, batchIndex, cropSizeW, cropSizeH);
}

Status AIPPParaBufferImpl::SetResizePara(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t resizeOutputSizeW, uint32_t resizeOutputSizeH)
{
    return HIAI_MR_TensorAippPara_SetResizePara(tensorAippPara, batchIndex, resizeOutputSizeW, resizeOutputSizeH);
}

Status AIPPParaBufferImpl::GetResizePara(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t* resizeOutputSizeW, uint32_t* resizeOutputSizeH)
{
    return HIAI_MR_TensorAippPara_GetResizePara(tensorAippPara, batchIndex, resizeOutputSizeW, resizeOutputSizeH);
}

Status AIPPParaBufferImpl::SetPadTopSize(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t paddingSizeTop)
{
    return HIAI_MR_TensorAippPara_SetPadTopSize(tensorAippPara, batchIndex, paddingSizeTop);
}

Status AIPPParaBufferImpl::SetPadBottomSize(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t paddingSizeBottom)
{
    return HIAI_MR_TensorAippPara_SetPadBottomSize(tensorAippPara, batchIndex, paddingSizeBottom);
}

Status AIPPParaBufferImpl::SetPadLeftSize(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t paddingSizeLeft)
{
    return HIAI_MR_TensorAippPara_SetPadLeftSize(tensorAippPara, batchIndex, paddingSizeLeft);
}

Status AIPPParaBufferImpl::SetPadRightSize(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t paddingSizeRight)
{
    return HIAI_MR_TensorAippPara_SetPadRightSize(tensorAippPara, batchIndex, paddingSizeRight);
}

Status AIPPParaBufferImpl::SetPadChannelValue(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t chnValue[], uint32_t chnNum)
{
    return HIAI_MR_TensorAippPara_SetPadChannelValue(tensorAippPara, batchIndex, chnValue, chnNum);
}

Status AIPPParaBufferImpl::GetPadTopSize(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t* paddingSizeTop)
{
    return HIAI_MR_TensorAippPara_GetPadTopSize(tensorAippPara, batchIndex, paddingSizeTop);
}

Status AIPPParaBufferImpl::GetPadBottomSize(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t* paddingSizeBottom)
{
    return HIAI_MR_TensorAippPara_GetPadBottomSize(tensorAippPara, batchIndex, paddingSizeBottom);
}

Status AIPPParaBufferImpl::GetPadLeftSize(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t* paddingSizeLeft)
{
    return HIAI_MR_TensorAippPara_GetPadLeftSize(tensorAippPara, batchIndex, paddingSizeLeft);
}

Status AIPPParaBufferImpl::GetPadRightSize(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t* paddingSizeRight)
{
    return HIAI_MR_TensorAippPara_GetPadRightSize(tensorAippPara, batchIndex, paddingSizeRight);
}

Status AIPPParaBufferImpl::GetPadChannelValue(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    uint32_t chnValue[], uint32_t chnNum)
{
    return HIAI_MR_TensorAippPara_GetPadChannelValue(tensorAippPara, batchIndex, chnValue, chnNum);
}

Status AIPPParaBufferImpl::SetDtcPixelMeanPara(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    int32_t pixelMeanPara[], uint32_t chnNum)
{
    return HIAI_MR_TensorAippPara_SetDtcPixelMeanPara(tensorAippPara, batchIndex, pixelMeanPara, chnNum);
}

Status AIPPParaBufferImpl::SetDtcPixelMinPara(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    float pixelMinPara[], uint32_t chnNum)
{
    return HIAI_MR_TensorAippPara_SetDtcPixelMinPara(tensorAippPara, batchIndex, pixelMinPara, chnNum);
}

Status AIPPParaBufferImpl::SetDtcPixelVarReciPara(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    float pixelVarReciPara[], uint32_t chnNum)
{
    return HIAI_MR_TensorAippPara_SetDtcPixelVarReciPara(tensorAippPara, batchIndex, pixelVarReciPara, chnNum);
}

Status AIPPParaBufferImpl::GetDtcPixelMeanPara(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    int32_t pixelMeanPara[], uint32_t chnNum)
{
    return HIAI_MR_TensorAippPara_GetDtcPixelMeanPara(tensorAippPara, batchIndex, pixelMeanPara, chnNum);
}

Status AIPPParaBufferImpl::GetDtcPixelMinPara(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    float pixelMinPara[], uint32_t chnNum)
{
    return HIAI_MR_TensorAippPara_GetDtcPixelMinPara(tensorAippPara, batchIndex, pixelMinPara, chnNum);
}

Status AIPPParaBufferImpl::GetDtcPixelVarReciPara(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    float pixelVarReciPara[], uint32_t chnNum)
{
    return HIAI_MR_TensorAippPara_GetDtcPixelVarReciPara(tensorAippPara, batchIndex, pixelVarReciPara, chnNum);
}

Status AIPPParaBufferImpl::SetRotatePara(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    float rotateAngle)
{
    return HIAI_MR_TensorAippPara_SetRotateAngle(tensorAippPara, batchIndex, rotateAngle);
}

Status AIPPParaBufferImpl::GetRotatePara(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex,
    float* rotateAngle)
{
    return HIAI_MR_TensorAippPara_GetRotateAngle(tensorAippPara, batchIndex, rotateAngle);
}

bool AIPPParaBufferImpl::GetCscSwitch(HIAI_MR_TensorAippPara* tensorAippPara)
{
    return HIAI_MR_TensorAippPara_GetCscSwitch(tensorAippPara);
}

bool AIPPParaBufferImpl::GetCropSwitch(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex)
{
    return HIAI_MR_TensorAippPara_GetCropSwitch(tensorAippPara, batchIndex);
}

bool AIPPParaBufferImpl::GetResizeSwitch(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex)
{
    return HIAI_MR_TensorAippPara_GetResizeSwitch(tensorAippPara, batchIndex);
}

bool AIPPParaBufferImpl::GetPaddingSwitch(HIAI_MR_TensorAippPara* tensorAippPara, uint32_t batchIndex)
{
    return HIAI_MR_TensorAippPara_GetPadSwitch(tensorAippPara, batchIndex);
}

Status AIPPParaImpl::Init(uint32_t batchCount)
{
    if (paraBuff_ != nullptr) {
        FMK_LOGI("AIPPParaImpl is already inited!");
        return FAILURE;
    }

    HIAI_MR_TensorAippPara* paraBuff = AIPPParaBufferImpl::Init(batchCount);
    HIAI_EXPECT_NOT_NULL_R(paraBuff, FAILURE);

    // initial
    paraBuff_ = paraBuff;
    rawBuffer_ = AIPPParaBufferImpl::GetRawBuffer(paraBuff);
    if (InitAippPara(batchCount) != SUCCESS) {
        FMK_LOGE("Init error, InitAippPara is failed!");
        return FAILURE;
    }
    return SUCCESS;
}

Status AIPPParaImpl::Init(HIAI_MR_TensorAippPara* paraBuff)
{
    HIAI_EXPECT_TRUE(paraBuff_ == nullptr);
    HIAI_EXPECT_TRUE(rawBuffer_ == nullptr);
    HIAI_EXPECT_NOT_NULL(paraBuff);

    void* buffer = AIPPParaBufferImpl::GetRawBuffer(paraBuff);
    if (buffer == nullptr) {
        FMK_LOGE("Init error, paraBuff is not invailed!");
        return FAILURE;
    }

    paraBuff_ = paraBuff;
    rawBuffer_ = buffer;
    return SUCCESS;
}

AIPPParaImpl::~AIPPParaImpl()
{
    AIPPParaBufferImpl::Release(paraBuff_);

    paraBuff_ = nullptr;
    rawBuffer_ = nullptr;
}

Status AIPPParaImpl::InitAippPara(uint32_t batchCount)
{
    HIAI_EXPECT_TRUE_R(batchCount > 0 && batchCount <= g_maxBatchNum, FAILURE);

    float pixelVarReciPara[4] = {1.0, 1.0, 1.0, 1.0};

    for (uint32_t batchIndex = 0; batchIndex < batchCount; ++batchIndex) {
        HIAI_EXPECT_EXEC(AIPPParaBufferImpl::SetDtcPixelVarReciPara(paraBuff_, batchIndex, pixelVarReciPara, 4));
    }
    return SUCCESS;
}

void* AIPPParaImpl::GetData()
{
    return rawBuffer_;
}

size_t AIPPParaImpl::GetSize() const
{
    return AIPPParaBufferImpl::GetRawBufferSize(paraBuff_);
}

uint32_t AIPPParaImpl::GetBatchCount()
{
    return AIPPParaBufferImpl::GetBatchCount(paraBuff_);
}

Status AIPPParaImpl::SetInputIndex(uint32_t inputIndex)
{
    if (paraBuff_ == nullptr) {
        FMK_LOGE("SetInputIndex error, AippPara is not inited!");
        return FAILURE;
    }

    AIPPParaBufferImpl::SetInputIndex(paraBuff_, inputIndex);
    return SUCCESS;
}

int32_t AIPPParaImpl::GetInputIndex()
{
    if (paraBuff_ == nullptr) {
        FMK_LOGE("GetInputIndex error, AippPara is not inited!");
        return -1;
    }

    int32_t ret = AIPPParaBufferImpl::GetInputIndex(paraBuff_);
    if (ret == -1) {
        FMK_LOGE("GetInputIndex error, inner error occurred");
    }
    return ret;
}

Status AIPPParaImpl::SetInputAippIndex(uint32_t inputAippIndex)
{
    if (paraBuff_ == nullptr) {
        FMK_LOGE("SetInputAippIndex error, AippPara is not inited!");
        return FAILURE;
    }

    AIPPParaBufferImpl::SetInputAippIndex(paraBuff_, inputAippIndex);
    return SUCCESS;
}

int32_t AIPPParaImpl::GetInputAippIndex()
{
    if (paraBuff_ == nullptr) {
        FMK_LOGE("GetInputAippIndex error, AippPara is not inited!");
        return -1;
    }

    int32_t ret = AIPPParaBufferImpl::GetInputAippIndex(paraBuff_);
    if (ret == -1) {
        FMK_LOGE("GetInputAippIndex error, inner error occurred");
    }
    return ret;
}

Status AIPPParaImpl::SetCscPara(ImageFormat targetFormat, ImageColorSpace colorSpace)
{
    HIAI_EXPECT_NOT_NULL_R(paraBuff_, FAILURE);

    ImageFormat inputFormat = GetInputFormat();
    HIAI_EXPECT_TRUE_R(inputFormat != ImageFormat::INVALID, FAILURE);

    std::set<ImageFormat> validFormat = {
        ImageFormat::YVU444SP, ImageFormat::YUV444SP, ImageFormat::RGB888, ImageFormat::BGR888, ImageFormat::YUV400};
    if (validFormat.find(targetFormat) == validFormat.end()) {
        FMK_LOGE("targetFormat is not in valid range of [ YVU444SP, YUV444SP, RGB888, BGR888, YUV400 ]");
        return FAILURE;
    }

    Status ret = AIPPParaBufferImpl::SetCscPara(paraBuff_, inputFormat, targetFormat, colorSpace);
    if (ret == SUCCESS) {
        targetFormat_ = targetFormat;
        colorSpace_ = colorSpace;
    }
    return ret;
}

Status AIPPParaImpl::SetCscPara(CscMatrixPara cscPara)
{
    HIAI_EXPECT_NOT_NULL_R(paraBuff_, FAILURE);

    return AIPPParaBufferImpl::SetCscMatrixPara(paraBuff_, cscPara);
}

CscPara AIPPParaImpl::GetCscPara()
{
    CscPara cscPara;
    HIAI_EXPECT_NOT_NULL_R(paraBuff_, cscPara);

    (void)AIPPParaBufferImpl::GetCscPara(
        paraBuff_, &cscPara.imageFormat, &cscPara.outputFormat, &cscPara.imageColorSpace);
    return cscPara;
}

CscMatrixPara AIPPParaImpl::GetCscMatrixPara()
{
    CscMatrixPara cscPara;
    HIAI_EXPECT_NOT_NULL_R(paraBuff_, cscPara);

    Status ret = AIPPParaBufferImpl::GetCscMatrixPara(paraBuff_, &cscPara);
    if (ret == SUCCESS) {
        cscPara.outputFormat = targetFormat_;
        cscPara.colorSpace = colorSpace_;
    }
    return cscPara;
}

Status AIPPParaImpl::SetChannelSwapPara(ChannelSwapPara&& channelSwapPara)
{
    HIAI_EXPECT_NOT_NULL_R(paraBuff_, FAILURE);

    HIAI_EXPECT_EXEC(AIPPParaBufferImpl::SetChannelSwapPara(
        paraBuff_, channelSwapPara.rbuvSwapSwitch, channelSwapPara.axSwapSwitch));
    return SUCCESS;
}

ChannelSwapPara AIPPParaImpl::GetChannelSwapPara()
{
    ChannelSwapPara channelSwapPara;
    HIAI_EXPECT_NOT_NULL_R(paraBuff_, channelSwapPara);

    (void)AIPPParaBufferImpl::GetChannelSwapPara(
        paraBuff_, &channelSwapPara.rbuvSwapSwitch, &channelSwapPara.axSwapSwitch);
    return channelSwapPara;
}

Status AIPPParaImpl::SetSingleBatchMultiCrop(bool singleBatchMutiCrop)
{
    HIAI_EXPECT_NOT_NULL_R(paraBuff_, FAILURE);

    HIAI_EXPECT_EXEC(AIPPParaBufferImpl::SetSingleBatchMultiCrop(paraBuff_, singleBatchMutiCrop));

    return SUCCESS;
}

bool AIPPParaImpl::GetSingleBatchMultiCrop()
{
    return AIPPParaBufferImpl::GetSingleBatchMultiCrop(paraBuff_);
}
// end common interface

template <typename T, typename UpdateParaFunc>
Status AIPPParaImpl::SetAippFuncPara(T&& funcPara, UpdateParaFunc updateParaFunc)
{
    uint32_t batchCount = GetBatchCount();
    HIAI_EXPECT_TRUE_R(batchCount > 0 && batchCount <= g_maxBatchNum, FAILURE);
    HIAI_EXPECT_NOT_NULL_R(paraBuff_, FAILURE);

    for (uint32_t index = 0; index < batchCount; ++index) {
        updateParaFunc(paraBuff_, index, funcPara);
    }
    return SUCCESS;
}

template <typename T, typename UpdateParaFunc>
Status AIPPParaImpl::SetAippFuncPara(uint32_t batchIndex, T&& funcPara, UpdateParaFunc updateParaFunc)
{
    uint32_t batchCount = GetBatchCount();
    HIAI_EXPECT_TRUE_R(batchCount > 0 && batchCount <= g_maxBatchNum, FAILURE);
    HIAI_EXPECT_EXEC(CheckBatchIndex(batchIndex, batchCount));

    HIAI_EXPECT_NOT_NULL(paraBuff_);
    return updateParaFunc(paraBuff_, batchIndex, funcPara);
}

Status AIPPParaImpl::SetCropPara(CropPara&& cropPara)
{
    return SetAippFuncPara(cropPara, UpdateCropPara);
}

Status AIPPParaImpl::SetCropPara(uint32_t batchIndex, CropPara&& cropPara)
{
    return SetAippFuncPara(batchIndex, cropPara, UpdateCropPara);
}

CropPara AIPPParaImpl::GetCropPara(uint32_t batchIndex)
{
    CropPara cropPara;
    cropPara.batchIndex = batchIndex;
    (void)AIPPParaBufferImpl::GetCropPos(paraBuff_, batchIndex, &cropPara.cropStartPosW, &cropPara.cropStartPosH);
    (void)AIPPParaBufferImpl::GetCropSize(paraBuff_, batchIndex, &cropPara.cropSizeW, &cropPara.cropSizeH);

    return cropPara;
}

Status AIPPParaImpl::SetResizePara(ResizePara&& resizePara)
{
    return SetAippFuncPara(resizePara, UpdateResizePara);
}

Status AIPPParaImpl::SetResizePara(uint32_t batchIndex, ResizePara&& resizePara)
{
    return SetAippFuncPara(batchIndex, resizePara, UpdateResizePara);
}

ResizePara AIPPParaImpl::GetResizePara(uint32_t batchIndex)
{
    ResizePara resizePara;
    resizePara.batchIndex = batchIndex;
    (void)AIPPParaBufferImpl::GetResizePara(
        paraBuff_, batchIndex, &resizePara.resizeOutputSizeW, &resizePara.resizeOutputSizeH);
    return resizePara;
}

Status AIPPParaImpl::SetPaddingPara(PadPara&& paddingPara)
{
    return SetAippFuncPara(paddingPara, UpdatePaddingPara);
}

Status AIPPParaImpl::SetPaddingPara(uint32_t batchIndex, PadPara&& paddingPara)
{
    return SetAippFuncPara(batchIndex, paddingPara, UpdatePaddingPara);
}

PadPara AIPPParaImpl::GetPaddingPara(uint32_t batchIndex)
{
    PadPara padPara;
    padPara.batchIndex = batchIndex;
    uint32_t chnValue[4] = {0};
    (void)AIPPParaBufferImpl::GetPadTopSize(paraBuff_, batchIndex, &padPara.paddingSizeTop);
    (void)AIPPParaBufferImpl::GetPadBottomSize(paraBuff_, batchIndex, &padPara.paddingSizeBottom);
    (void)AIPPParaBufferImpl::GetPadLeftSize(paraBuff_, batchIndex, &padPara.paddingSizeLeft);
    (void)AIPPParaBufferImpl::GetPadRightSize(paraBuff_, batchIndex, &padPara.paddingSizeRight);
    (void)AIPPParaBufferImpl::GetPadChannelValue(paraBuff_, batchIndex, chnValue, 4);

    padPara.paddingValueChn0 = SaveUint16ToFp16(static_cast<uint16_t>(chnValue[0]));
    padPara.paddingValueChn1 = SaveUint16ToFp16(static_cast<uint16_t>(chnValue[1]));
    padPara.paddingValueChn2 = SaveUint16ToFp16(static_cast<uint16_t>(chnValue[2]));
    padPara.paddingValueChn3 = SaveUint16ToFp16(static_cast<uint16_t>(chnValue[3]));

    return padPara;
}

Status AIPPParaImpl::SetDtcPara(DtcPara&& dtcPara)
{
    return SetAippFuncPara(dtcPara, UpdateDtcPara);
}

Status AIPPParaImpl::SetDtcPara(uint32_t batchIndex, DtcPara&& dtcPara)
{
    return SetAippFuncPara(batchIndex, dtcPara, UpdateDtcPara);
}

DtcPara AIPPParaImpl::GetDtcPara(uint32_t batchIndex)
{
    DtcPara dtcPara;
    int32_t pixelMeanPara[4] = {0};
    float pixelMinPara[4] = {0.0};
    float pixelVarReciPara[4] = {0.0};

    (void)AIPPParaBufferImpl::GetDtcPixelMeanPara(paraBuff_, batchIndex, pixelMeanPara, 4);
    (void)AIPPParaBufferImpl::GetDtcPixelMinPara(paraBuff_, batchIndex, pixelMinPara, 4);
    (void)AIPPParaBufferImpl::GetDtcPixelVarReciPara(paraBuff_, batchIndex, pixelVarReciPara, 4);

    dtcPara.pixelMeanChn0 = static_cast<int16_t>(pixelMeanPara[0]);
    dtcPara.pixelMeanChn1 = static_cast<int16_t>(pixelMeanPara[1]);
    dtcPara.pixelMeanChn2 = static_cast<int16_t>(pixelMeanPara[2]);
    dtcPara.pixelMeanChn3 = static_cast<int16_t>(pixelMeanPara[3]);
    dtcPara.pixelMinChn0 = pixelMinPara[0];
    dtcPara.pixelMinChn1 = pixelMinPara[1];
    dtcPara.pixelMinChn2 = pixelMinPara[2];
    dtcPara.pixelMinChn3 = pixelMinPara[3];
    dtcPara.pixelVarReciChn0 = pixelVarReciPara[0];
    dtcPara.pixelVarReciChn1 = pixelVarReciPara[1];
    dtcPara.pixelVarReciChn2 = pixelVarReciPara[2];
    dtcPara.pixelVarReciChn3 = pixelVarReciPara[3];

    return dtcPara;
}

Status AIPPParaImpl::SetRotatePara(RotatePara&& rotatePara)
{
    return SetAippFuncPara(rotatePara, UpdateRotatePara);
}

Status AIPPParaImpl::SetRotatePara(uint32_t batchIndex, RotatePara&& rotatePara)
{
    return SetAippFuncPara(batchIndex, rotatePara, UpdateRotatePara);
}

RotatePara AIPPParaImpl::GetRotatePara(uint32_t batchIndex)
{
    RotatePara rotatePara;
    rotatePara.batchIndex = batchIndex;

    (void)AIPPParaBufferImpl::GetRotatePara(paraBuff_, batchIndex, &rotatePara.rotationAngle);

    return rotatePara;
}

Status AIPPParaImpl::SetInputFormat(ImageFormat inputFormat)
{
    return AIPPParaBufferImpl::SetInputFormat(paraBuff_, inputFormat);
}

ImageFormat AIPPParaImpl::GetInputFormat()
{
    return static_cast<ImageFormat>(AIPPParaBufferImpl::GetInputFormat(paraBuff_));
}

std::vector<int32_t> AIPPParaImpl::GetInputShape()
{
    uint32_t srcImageW = 0;
    uint32_t srcImageH = 0;
    AIPPParaBufferImpl::GetInputShape(paraBuff_, &srcImageW, &srcImageH);
    std::vector<int32_t> shape;
    shape.push_back(static_cast<int32_t>(srcImageW));
    shape.push_back(static_cast<int32_t>(srcImageH));
    return shape;
}

Status AIPPParaImpl::SetInputShape(std::vector<int32_t>& shape)
{
    if (shape.size() != 2) {
        FMK_LOGE("shape invalid!");
        return FAILURE;
    }
    if (paraBuff_ == nullptr) {
        FMK_LOGE("SetInputShape error, AippPara is not inited!");
        return FAILURE;
    }
    AIPPParaBufferImpl::SetInputShape(paraBuff_, static_cast<uint32_t>(shape[0]), static_cast<uint32_t>(shape[1]));

    return SUCCESS;
}

Status AIPPParaImpl::GetAippParaBufferImpl(std::shared_ptr<AIPPParaBufferImpl>& aippParaImpl)
{
    aippParaImpl = make_shared_nothrow<AIPPParaBufferImpl>();
    if (aippParaImpl == nullptr) {
        return FAILURE;
    }
    return SUCCESS;
}

HIAI_MR_TensorAippPara* AIPPParaImpl::GetParaBuffer()
{
    return paraBuff_;
}

bool AIPPParaImpl::GetEnableCsc()
{
    HIAI_EXPECT_NOT_NULL_R(paraBuff_, false);
    return AIPPParaBufferImpl::GetCscSwitch(paraBuff_);
}

bool AIPPParaImpl::GetEnableCrop(uint32_t batchIndex)
{
    HIAI_EXPECT_NOT_NULL_R(paraBuff_, false);
    return AIPPParaBufferImpl::GetCropSwitch(paraBuff_, batchIndex);
}

bool AIPPParaImpl::GetEnableResize(uint32_t batchIndex)
{
    HIAI_EXPECT_NOT_NULL_R(paraBuff_, false);
    return AIPPParaBufferImpl::GetResizeSwitch(paraBuff_, batchIndex);
}

bool AIPPParaImpl::GetEnablePadding(uint32_t batchIndex)
{
    HIAI_EXPECT_NOT_NULL_R(paraBuff_, false);
    return AIPPParaBufferImpl::GetPaddingSwitch(paraBuff_, batchIndex);
}

std::shared_ptr<IAIPPPara> CreateAIPPPara(uint32_t batchCount)
{
#ifdef __OHOS__
    if (!NDKUtil::CanDlopenVendorSo()) {
        return CreateAIPPParaFromNDK(batchCount);
    }
#endif
    shared_ptr<AIPPParaImpl> aippPara = make_shared_nothrow<AIPPParaImpl>();
    if (aippPara == nullptr) {
        FMK_LOGE("create aippParaImpl failed.");
        return nullptr;
    }
    auto status = aippPara->Init(batchCount);
    if (status != SUCCESS) {
        FMK_LOGE("create aippPara failed.");
        return nullptr;
    }
    return aippPara;
}
HIAI_MR_TensorAippPara* GetTensorAippParaFromAippPara(const std::shared_ptr<IAIPPPara>& aippPara)
{
    std::shared_ptr<AIPPParaImpl> aippParaImpl = std::dynamic_pointer_cast<AIPPParaImpl>(aippPara);
    if (aippParaImpl == nullptr) {
        FMK_LOGE("invalid aippPara");
        return nullptr;
    }
    return aippParaImpl->GetParaBuffer();
}

} // namespace hiai